home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / finds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  18.8 KB  |  773 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <ctype.h>
  9. #include <unistd.h>
  10. #include <limits.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14.  
  15. #define FINDS_C
  16. #define I_BUFFLOOP_C
  17. #define I_DISPLAY_C
  18. #define I_FIELDEDIT_C
  19. #define I_FOLDHELP_C
  20. #define I_FOLDING_C
  21. #define I_GETTK_C
  22. #define I_GETMSG_C
  23. #define I_KEYBOARD_C
  24. #define I_LOOP_C
  25. #define I_MAIN_C
  26. #define I_MISC_C
  27. #define I_MESSAGES_C
  28. #define I_ORIEDT_C
  29. #define I_PROMPT_C
  30. #define I_SCREEN_C
  31. #define I_STRING_C
  32.  
  33. #define I_VIRTUAL_C
  34.  
  35. #include "origami.h"
  36. #include <lib/ori_add_lib.h>
  37. #ifdef REGEXP
  38. #  include <lib/ori_re_lib.h>
  39. #endif
  40. /*}}}  */
  41.  
  42. /*{{{  variables*/
  43. public unsigned char item_to_look_for[LINELEN+1];
  44. #ifdef REGEXP
  45.    public boolean inverted_search;
  46. #else
  47. #  define inverted_search False
  48. #endif
  49. private unsigned char replace_item[LINELEN+1];
  50. /*}}}  */
  51.  
  52. /*{{{  line_no*/
  53. public int line_no(element const *q,element const * const from)
  54. {
  55.   int i;
  56.   element const *p;
  57.   boolean c_c_l;
  58.   linetyp lt;
  59.  
  60.   if (!q || !from || !bd.f.real_head)
  61.      return(0);
  62.   c_c_l=    bd.f.count_comment_line
  63.          && (bd.m.dialect.typ!=F_C_NONE && bd.m.dialect.typ!=F_C_TDS);
  64.   i = 0;
  65.   if ((p=from)==bd.f.real_head)
  66.      p=move_on(p);
  67.   for (lt=get_linetyp(*p);p!=q;)
  68.    { if (lt&NOT_FOLD)
  69.         i++;
  70.      else if (lt&START_FILED)
  71.         i += 3;
  72.      else if (normal_att(&(p->x.fold),False) || bd.m.dialect.typ==F_C_TDS)
  73.         i++;
  74.      else
  75.         i+=2;
  76.      if (p==bd.f.real_tail)
  77.         break;
  78.      /*{{{  move_on hard coded. This is time-critical!*/
  79.      if (lt&START_FOLD)
  80.         p=p->x.fold.data;
  81.      else
  82.         p=p->next;
  83.      /*}}}  */
  84.      lt=get_linetyp(*p);
  85.      if (c_c_l && lt!=NOT_FOLD) { i++;c_c_l=False; }
  86.    }
  87.   return i;
  88. }
  89. /*}}}  */
  90. /*{{{  cur_line_no*/
  91. public int cur_line_no(void)
  92. { int x;
  93.  
  94.   if (!(x=title_op(LINE_NO)))
  95.      x=line_no(bd.f.current,bd.f.real_head);
  96.   return(x);
  97. }
  98. /*}}}  */
  99. /*{{{  close_and_open_folds*/
  100. public void close_and_open_folds(element * const qq)
  101. {
  102.   element *q;
  103.   element *old_q;
  104.  
  105.   q=qq;
  106.   while (q != bd.f.head)
  107.    { old_q = q;
  108.      q = q->prec;
  109.      if (test_linetyp(*q,START_FOLD) && q->x.fold.data==old_q)
  110.         pre_open_fold(q);
  111.      if (test_linetyp(*q,END_FOLD))
  112.       { if (test_linetyp(*(q->x.fold.other_end),START_OPEN_FOLD))
  113.          { q = q->x.fold.other_end;
  114.            close_fold_at(q);
  115.          }
  116.       }
  117.    }
  118.   q = qq;
  119.   while (q != bd.f.tail)
  120.    { q = q->next;
  121.      if (test_linetyp(*q,START_OPEN_FOLD))
  122.         close_fold_at(q);
  123.    }
  124. }
  125. /*}}}  */
  126. /*{{{  ptr_find_item*/
  127. private unsigned char *ptr_find_item
  128.  ( boolean backup,
  129.    boolean display,
  130.    boolean do_enable_abort
  131.    re_args(reg_types magic)
  132.  )
  133.  {
  134.    int position;
  135.    element *p, *q;
  136.    unsigned char *ptr_found;
  137.    /*{{{  USTRSTR*/
  138. #   ifdef REGEXP
  139. #     define USTRSTR(s,b,e) (magic?reg_ustrstr(s,b,e):ustrstr(s,item_to_look_for))
  140. #   else
  141. #     define USTRSTR(s,b,e) (ustrstr(s,item_to_look_for))
  142. #   endif
  143.    /*}}}  */
  144.  
  145.    if (!executing_macro && do_enable_abort)
  146.       enable_abort();
  147.    q=p=bd.f.current;
  148.    ptr_found=0;
  149.    copyin(line_buffer,p,False);
  150.    position=scr2txt(bd.f.enter_spaces,bd.scr.cursor.w,line_buffer);
  151.    if (backup)
  152.     /*{{{  search reverse*/
  153.     { while (p!=bd.f.head->next && !ptr_found && !aborted)
  154.        { unsigned char *f;
  155.  
  156.          copyin(line_buffer,p,False);
  157.          if (inverted_search && p==bd.f.current)
  158.           /*{{{  ! doesn't match current line, set to it, toggled below*/
  159.             f=line_buffer;
  160.           /*}}}  */
  161.          else
  162.           /*{{{  set f to latest occurance*/
  163.           { unsigned char *f_new;
  164.             unsigned char *f_max;
  165.  
  166.             f_max=line_buffer+((p==bd.f.current)?position:ustrlen(line_buffer));
  167.             if ((f=f_new=USTRSTR(line_buffer,True,True)))
  168.                while
  169.                 (    (f_new=USTRSTR(f_new+1,False,True))
  170.                   && f_new<f_max
  171.                 )
  172.                   f=f_new;
  173.             if (f==f_max)
  174.                f=0;
  175.           }
  176.           /*}}}  */
  177.          /*{{{  maybe !, so toggle result of search*/
  178.          if (inverted_search)
  179.             f=f?0:(line_buffer+p->indent);
  180.          /*}}}  */
  181.          if (f)
  182.           { ptr_found=f;
  183.             position=f-line_buffer;
  184.           }
  185.          else if (test_linetyp(*(p->prec),START_FOLD) && p->prec->next==p)
  186.             p=p->prec->x.fold.other_end;
  187.          else
  188.             p=p->prec;
  189.        }
  190.     }
  191.     /*}}}  */
  192.    else
  193.     /*{{{  search forward*/
  194.     { while (p!=bd.f.tail && !ptr_found && !aborted)
  195.        { unsigned char *f;
  196.  
  197.          copyin(line_buffer,p,False);
  198.          /*{{{  check line*/
  199.          if (p != bd.f.current)
  200.           /*{{{  search in whole line*/
  201.           { f=USTRSTR(line_buffer+p->indent,True,True);
  202.             if (inverted_search)
  203.                f=f?0:(line_buffer+p->indent);
  204.           }
  205.           /*}}}  */
  206.          else if (inverted_search)
  207.           /*{{{  ! matches never the current line*/
  208.             f=0;
  209.           /*}}}  */
  210.          else if (position>=ustrlen(line_buffer))
  211.           /*{{{  behind end of line doesn't match*/
  212.             f=0;
  213.           /*}}}  */
  214.          else
  215.           /*{{{  check inside line, from position on*/
  216.             f=USTRSTR(line_buffer+position,False,True);
  217.           /*}}}  */
  218.          /*}}}  */
  219.          if (f==0)
  220.             p=move_on(p);
  221.          else
  222.           { ptr_found=f;
  223.             position=f-line_buffer;
  224.           }
  225.        }
  226.     }
  227.     /*}}}  */
  228.    if (!executing_macro && do_enable_abort)
  229.       disable_abort();
  230.    if (ptr_found)
  231.       if (aborted)
  232.          ptr_found=0;
  233.       else
  234.        { if (p != q)
  235.           /*{{{  move and maybe open folds*/
  236.           { int off;
  237.  
  238.             off=ustrlen(line_buffer);
  239.             /*{{{  handle display/folds*/
  240.             if (on_screen(p) && display)
  241.                skip_to(p);
  242.             else
  243.              { bd.f.cur_line_typ=get_linetyp(*(bd.f.current=p));
  244.                close_and_open_folds(p);
  245.                if (display)
  246.                   restore_element(bd.scr.txt_size.h/2);
  247.              }
  248.             /*}}}  */
  249.             copyin(line_buffer, p, False);
  250.             position+=ustrlen(line_buffer)-off;
  251.           }
  252.           /*}}}  */
  253.          bd.scr.cursor.w=txt2scr(bd.f.enter_spaces,position,line_buffer);
  254.          title_op(CHGXY);
  255.        }
  256.    return(ptr_found);
  257.  
  258. #  undef USTRSTR
  259.  }
  260. /*}}}  */
  261. /*{{{  find_item*/
  262. public boolean find_item
  263.  ( boolean backup,
  264.    boolean display,
  265.    boolean do_enable_abort
  266.    re_args(reg_types magic)
  267.  )
  268.  {
  269.    return
  270.     (ptr_find_item(backup,display,do_enable_abort re_args(magic))?True:False);
  271.  }
  272. /*}}}  */
  273. /*{{{  pre_find_element*/
  274. public element *pre_find_element(int new_line_no)
  275. {
  276.   int current_line_no;
  277.   element *p;
  278.   boolean c_c_l;
  279.  
  280.   for
  281.    ( current_line_no=0,p=bd.f.head->next,
  282.      c_c_l=     bd.f.count_comment_line
  283.             && (bd.m.dialect.typ!=F_C_NONE && bd.m.dialect.typ!=F_C_TDS)
  284.    ; current_line_no<new_line_no && p!=bd.f.tail
  285.    ; p=move_on(p)
  286.    )
  287.      switch(get_linetyp(*p))
  288.       { case START_FILED:
  289.            current_line_no+=2;
  290.         default:
  291.            if (c_c_l && p!=bd.f.head->next)
  292.             { current_line_no++;
  293.               c_c_l=False;
  294.             }
  295.         case NOT_FOLD:
  296.            current_line_no++;
  297.            break;
  298.       }
  299.  
  300.   return p;
  301. }
  302. /*}}}  */
  303. /*{{{  find_element*/
  304. public void find_element(int new_line_no, int close_line)
  305. {
  306.   element *p;
  307.  
  308.   pre_top_fold();
  309.   p = pre_find_element(new_line_no);
  310.   close_and_open_folds(p);
  311.   bd.f.current = p;
  312.   title_op(CHGXY);
  313.   restore_element(close_line);
  314. }
  315. /*}}}  */
  316. /*{{{  goto_line*/
  317. public void goto_line(int no,element *p,boolean no_force)
  318. {
  319.   if (no_force && p && p==bd.f.current)
  320.      return;
  321.  
  322.   pre_top_fold();
  323.   if (!p)
  324.    /*{{{  prompt for line number and get corresponding element*/
  325.    {
  326. #    define LINE_SIZE 16
  327.      unsigned char command_str[LINE_SIZE+1];
  328.  
  329.      s_readprompt(command_str,get_msg(M_GOTO),LINE_SIZE,misc_history);
  330.      if (command_str[0])
  331.       { no=atoi((char *)command_str);
  332.         p=pre_find_element(no);
  333.       }
  334.    }
  335.    /*}}}  */
  336.   else
  337.    /*{{{  check, if p in buffer!*/
  338.    { element *q;
  339.  
  340.      q=bd.f.real_head;
  341.      q=move_on(q);
  342.      while (p!=q)
  343.       { if (q==bd.f.real_tail)
  344.          { p=bd.f.tail;
  345.            break;
  346.          }
  347.         q=move_on(q);
  348.       }
  349.    }
  350.    /*}}}  */
  351.   if (p)
  352.    { bd.scr.cursor.w = 1;
  353.      close_and_open_folds(p);
  354.      bd.f.current = p;
  355.      title_op(CHGXY);
  356.      restore_element(bd.scr.txt_size.h/2);
  357.    }
  358. }
  359. /*}}}  */
  360. /*{{{  find_field*/
  361. private void find_field(void)
  362. { int off;
  363.   int txt_off;
  364.   int x;
  365.   int m1,m2;
  366.   int y;
  367.  
  368.   if (bd.scr.cursor.w<1) return;
  369.   copyin(line_buffer, bd.f.current, False);
  370.   x_shift(&off,&txt_off,0,bd.scr.cursor.w,bd.f.enter_spaces,line_buffer);
  371.   restore_shift(off);
  372.   /*{{{  handle higlight borders*/
  373.   switch (get_highlight(*bd.f.current))
  374.    {
  375.      /*{{{  c_f*/
  376.      case c_f_highlight:
  377.         m1=bd.scr.cursor.w;
  378.         m2=LINELEN+3;
  379.         break;
  380.      /*}}}  */
  381.      /*{{{  m_f*/
  382.      case m_f_highlight:
  383.         m1=bd.e.makefold_indent;
  384.         m2=LINELEN+3;
  385.         break;
  386.      /*}}}  */
  387.      /*{{{  f_m*/
  388.      case f_m_highlight:
  389.         m1=0;
  390.         m2=bd.scr.cursor.w-1;
  391.         break;
  392.      /*}}}  */
  393.      /*{{{  c_m*/
  394.      case c_m_highlight:
  395.         if (bd.e.makefold_indent<bd.scr.cursor.w)
  396.          { m1=bd.e.makefold_indent;m2=bd.scr.cursor.w-1; }
  397.         else
  398.          { m2=bd.e.makefold_indent+1;m1=bd.scr.cursor.w-1;
  399.            if (m1<m2)
  400.               m1++;
  401.          }
  402.         break;
  403.      /*}}}  */
  404.      /*{{{  full*/
  405.      case full_highlight:
  406.         m1=0;
  407.         m2=LINELEN+2;
  408.         break;
  409.      /*}}}  */
  410.      /*{{{  no highlight:simply print*/
  411.      case no_highlight:
  412.      default:
  413.         m1=LINELEN+2;
  414.         m2=LINELEN+3;
  415.         break;
  416.      /*}}}  */
  417.    }
  418.   /*}}}  */
  419.   move_cursor_to(y=bd.scr.cursor.h+bd.scr.off.h,1+bd.scr.off.w);
  420.   x=prt_highlight_bin_text(m1-off,m2-off,bd.f.enter_spaces+off,bd.scr.txt_size.w-1,True,line_buffer+txt_off);
  421.   if (x<bd.scr.txt_size.w) clrbuffline(bd.scr.cursor.h,x+1);
  422.   ori_assert(bd.scr.cur_shift_w<=LINELEN,"shift-check");
  423.   title_op(PRTTITLE);
  424.   if (off && soln_str)
  425.    { move_cursor_to(y,1+bd.scr.off.w);
  426.      oputc(soln_str);
  427.    }
  428.   move_cursor_to(y,bd.scr.cursor.w-off+bd.scr.off.w);
  429. }
  430. /*}}}  */
  431. /*{{{  query_replace*/
  432. public void query_replace(boolean force)
  433. {
  434.   unsigned char ch='\0';
  435.   boolean display=True;
  436.   boolean ok=True;
  437.   boolean done=False;
  438.  
  439.   ocl_var[var_ocl_arg].v= -1;
  440.   get_search(False,True,False);
  441.   if ((*item_to_look_for!='\0') && !aborted)
  442.    { s_readprompt(replace_item,get_msg(M_REPLACE),LINELEN,replace_history);
  443.      if (!aborted)
  444.       { int ls;
  445.  
  446.         ocl_var[var_ocl_arg].v=0;
  447.         ls=ustrlen(item_to_look_for);
  448.         while
  449.          (   !aborted
  450.           && find_item(False,display,ch!=DO_REST re_args(reg_type))
  451.          )
  452.          { copyin(cur_dsp_line, bd.f.current, False);
  453.            /*{{{  get next command, maybe prompt with menu*/
  454.            if (ch!=DO_REST)
  455.             { if (force)
  456.                  ch=DO_REST;
  457.               else
  458.                { title_op(CHGXY);
  459.                  msg_message(M_Q_R_PROMPT);
  460.                  find_field();
  461.                  ch=hide_key();
  462.                  ch=toupper(ch);
  463.                  if (ch==' ') ch=YES;
  464.                }
  465.               if (ch==DO_REST)
  466.                { display=False;
  467.                  if (!executing_macro)
  468.                     enable_abort();
  469.                }
  470.             }
  471.            /*}}}  */
  472.            if ((ch==YES || ch==DO_AB || ch==DO_REST) && !aborted)
  473.             /*{{{  do the replace*/
  474.             { int rp_len;
  475.  
  476.               done=True;
  477.               proc_to_edit_pos();
  478.               if (bd.scr.cursor.w<bd.e.first_scr_e_pos)
  479.                /*{{{  error on fold-marking pattern*/
  480.                { ok=False;
  481.                  msg_message(M_MARK_PATTERN);
  482.                  break;
  483.                }
  484.                /*}}}  */
  485.               /*{{{  replace and check*/
  486.               if
  487.                (0>(rp_len=proc_replace
  488.                            ( ls,
  489.                              replace_item,
  490.                              cur_dsp_line,
  491.                              scr2txt
  492.                               ( bd.f.enter_spaces,
  493.                                 bd.scr.cursor.w,
  494.                                 cur_dsp_line
  495.                               ),
  496.                              LINELEN-bd.f.enter_spaces
  497.                            )
  498.                   )
  499.                )
  500.                { ok=False;
  501.                  ocl_var[var_ocl_arg].v= -1;
  502.                  break;
  503.                }
  504.               /*}}}  */
  505.               proc_from_edit_pos();
  506.               move_cursor(rp_len);
  507.               copyout(cur_dsp_line, bd.f.current);
  508.               ocl_var[var_ocl_arg].v++;
  509.             }
  510.             /*}}}  */
  511.            else
  512.               move_cursor(1);
  513.            if (display)
  514.               write_dsp_line(bd.f.current, bd.scr.cursor.h);
  515.            if (ch==AB || ch==DO_AB)
  516.               break;
  517.          }
  518.         if (!executing_macro && ch==DO_REST)
  519.            disable_abort();
  520.         if (!display)
  521.            restore_element(bd.scr.txt_size.h/2);
  522.         if (ok)
  523.            no_message();
  524.       }
  525.    }
  526.   if (!done) try_unchange();
  527. }
  528. /*}}}  */
  529. /*{{{  do_replace*/
  530. public void do_replace(void)
  531. {
  532.   query_replace(True);
  533.   if (ocl_var[var_ocl_arg].v>=0)
  534.      message(get_msg(F_SUBSTITUTIONS,ocl_var[var_ocl_arg].v));
  535. }
  536. /*}}}  */
  537. /*{{{  its_search*/
  538. public void its_search(boolean reverse)
  539. {
  540.   /*{{{  variables*/
  541.   TOKEN c;
  542.   boolean first;
  543.   int hist_index=START_HISTORY_INDEX;
  544.   /*{{{  positions*/
  545.   win_data call;
  546.   win_data stack[LINELEN+1];
  547.   /*}}}  */
  548.   static unsigned char prompt[]="I-Search: ";
  549.   int i_lg;
  550.   boolean found;
  551.   boolean jmp_back=False;
  552. #  ifdef REGEXP
  553.      int re_err=0;
  554. #  endif
  555.   /*}}}  */
  556.  
  557.   /*{{{  screen off for highlight*/
  558.   if (bd.m.select_mode!=no_selection)
  559.      ocl_screen_off();
  560.   /*}}}  */
  561.   first=True;
  562. new_init:
  563.   found=True;
  564.   /*{{{  init search, prompt*/
  565.   i_lg=ustrlen(item_to_look_for);
  566.   if (jmp_back)
  567.    /*{{{  jump back*/
  568.    { bd.scr.cursor.w=stack[i_lg].w;
  569.      find_element(stack[i_lg].h,bd.scr.txt_size.h/2);
  570.      jmp_back=False;
  571.    }
  572.    /*}}}  */
  573.   else
  574. #  ifdef REGEXP
  575.        if (!re_err)
  576. #  endif
  577.       /*{{{  init position-stack*/
  578.       { int k=0;
  579.  
  580.         stack[0].w=bd.scr.cursor.w;
  581.         stack[0].h=cur_line_no();
  582.         while (++k <= i_lg) stack[k]=stack[0];
  583.         if (first) call=stack[0];
  584.       }
  585.       /*}}}  */
  586. #  ifdef REGEXP
  587.      if (reg_type)
  588.         re_err=item_to_look_for[0]?get_search(True,False,True):0;
  589. #  endif
  590.   find_field();
  591.   /*}}}  */
  592.   /*{{{  handle commands*/
  593.   do
  594.    {
  595.      /*{{{  store position in stack*/
  596.      title_op(CHGXY);
  597.      stack[i_lg].w=bd.scr.cursor.w;
  598.      stack[i_lg].h=cur_line_no();
  599.      /*}}}  */
  600.      /*{{{  screen on for highlight*/
  601.      if (bd.m.select_mode!=no_selection)
  602.       { ocl_screen_on();
  603.         upd_highlight(bd.f.real_head,bd.f.real_tail,True);
  604.         restore(1);
  605.       }
  606.      /*}}}  */
  607.      /*{{{  show prompt and position*/
  608.      title_op(CHGXY);
  609.      { enum dsp_size old_mode;
  610.  
  611.        old_mode=dsp.norm;
  612.        dsp.norm=norm_dsp;
  613.        moveclreol(message_line,1);
  614.        move_cursor_to(message_line,1);
  615.        prompt[0]=reverse?'R':'I';
  616.        prt_bin_text
  617.         ( 0,
  618.           LINELEN,
  619.           False,
  620. #     ifdef REGEXP
  621.           re_err
  622.            ? get_msg(M_REG_EXP,REG_ERR_TAG(re_err))
  623.            :
  624. #     endif
  625.               prompt
  626.         );
  627.       if (!first)
  628.          prt_bin_text(0,LINELEN,False,item_to_look_for);
  629. #     ifdef REGEXP
  630.        if (!re_err)
  631. #     endif
  632.           if (!found)
  633.              prt_bin_text(0,LINELEN,False,get_msg(M_FI_FAILED));
  634.        dsp.norm=old_mode;
  635.      }
  636.      find_field();
  637.      /*}}}  */
  638.      /*{{{  get command*/
  639.      do
  640.        c=hide_key();
  641.      while ((c==O_BREAK) && !aborted);
  642.      /*}}}  */
  643.      /*{{{  screen off for highlight or draw line again*/
  644.      if (bd.m.select_mode!=no_selection)
  645.         ocl_screen_off();
  646.      else
  647.         write_dsp_line(bd.f.current, bd.scr.cursor.h);
  648.      /*}}}  */
  649.      /*{{{  handle command*/
  650.      switch (c) {
  651.        /*{{{  O_DELETE*/
  652.        case O_DELETE:
  653.           first=False;
  654.           /*{{{  shorten string*/
  655.           if (i_lg)
  656.              item_to_look_for[--i_lg]='\0';
  657.           /*}}}  */
  658.           /*{{{  jump back*/
  659.           jmp_back=True;
  660.           goto new_init;
  661.           /*}}}  */
  662.        /*}}}  */
  663.        /*{{{  O_RETURN*/
  664.        case O_RETURN:
  665.           break;
  666.        /*}}}  */
  667.        /*{{{  O_FIND         O_RIGHT*/
  668.        case O_RIGHT:
  669.        case O_ITS_SEARCH:
  670.        case O_FIND:
  671.           first=False;
  672. #         ifdef REGEXP
  673.           if (re_err)
  674.              break;
  675. #         endif
  676.           reverse=False;
  677.           if (i_lg)
  678.            /*{{{  look for next*/
  679.            { move_cursor(1);
  680.              if (!(found=find_item(reverse,True,True re_args(reg_type))))
  681.                 move_cursor(-1);
  682.            }
  683.            /*}}}  */
  684.           else
  685.              found=True;
  686.           break;
  687.        /*}}}  */
  688.        /*{{{  O_FIND_REVERSE O_LEFT*/
  689.        case O_ITS_REVERSE:
  690.        case O_LEFT:
  691.        case O_FIND_REVERSE:
  692.           first=False;
  693. #         ifdef REGEXP
  694.           if (re_err)
  695.              break;
  696. #         endif
  697.           reverse=True;
  698.           if (i_lg)
  699.            /*{{{  look for previous*/
  700.              found=find_item(reverse,True,True re_args(reg_type));
  701.            /*}}}  */
  702.           else
  703.              found=True;
  704.           break;
  705.        /*}}}  */
  706.        /*{{{  O_DOWN O_UP*/
  707.        case O_DOWN:
  708.        case O_UP:
  709.         { unsigned char *s;
  710.  
  711.           first=False;
  712.           access_history
  713.            ( hist_index+((c==O_UP)?HISTORY_ADD_OLD:HISTORY_ADD_NEW),
  714.              search_history,True,&hist_index,&s
  715.            );
  716.           ustrcpy(item_to_look_for,s);
  717.           goto new_init;
  718.         }
  719.        /*}}}  */
  720.        /*{{{  ascii*/
  721.        default:
  722.          /*{{{  first: search-string= ascii*/
  723.          if (first)
  724.           { i_lg=0;
  725.             item_to_look_for[0]='\0';
  726.             first=False;
  727.           }
  728.          /*}}}  */
  729.          /*{{{  ignore keys >=O_NOP*/
  730.          if (c>=O_NOP)
  731.             break;
  732.          /*}}}  */
  733.          /*{{{  append char to search-string*/
  734.          item_to_look_for[i_lg++]=c;
  735.          item_to_look_for[i_lg]='\0';
  736.          /*}}}  */
  737. #        ifdef REGEXP
  738.             if (reg_type && (re_err=get_search(True,False,True)))
  739.              { stack[i_lg]=stack[i_lg-1];
  740.                goto new_init;
  741.              }
  742. #        endif
  743.          if (reverse)
  744.             move_cursor(1);
  745.          found=find_item(reverse,True,True re_args(reg_type));
  746.          if (reverse && !found)
  747.             move_cursor(-1);
  748.          break;
  749.        /*}}}  */
  750.      }
  751.      /*}}}  */
  752.    }
  753.   while (c!=O_BREAK && !aborted && c!=O_RETURN);
  754.   /*}}}  */
  755.   /*{{{  screen on for highlight*/
  756.   if (bd.m.select_mode!=no_selection)
  757.    { ocl_screen_on();
  758.      upd_highlight(bd.f.real_head,bd.f.real_tail,True);
  759.      restore(1);
  760.    }
  761.   /*}}}  */
  762.   /*{{{  <> O_RETURN -> jump to calling position*/
  763.   if (c!=O_RETURN)
  764.    { find_element(call.h,bd.scr.txt_size.h/2);
  765.      bd.scr.cursor.w=call.w;
  766.    }
  767.   /*}}}  */
  768.   if (item_to_look_for[0])
  769.      add_history(search_history,item_to_look_for);
  770.   message(empty_text);
  771. }
  772. /*}}}  */
  773.